package com.sunwayworld.basemodule.business.ordertask.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.sunwayworld.basemodule.basedata.sampletype.bean.LimsSampleTypeBean;
import com.sunwayworld.basemodule.basedata.sampletype.service.LimsSampleTypeService;
import com.sunwayworld.basemodule.business.batch.service.LimsBatchSampleProductService;
import com.sunwayworld.basemodule.business.operationbatch.bean.LimsOrderTaskSupplementBean;
import com.sunwayworld.basemodule.business.operationbatch.service.LimsOrderTaskSupplementService;
import com.sunwayworld.basemodule.business.ordertask.bean.LimsOrderTaskBean;
import com.sunwayworld.basemodule.business.ordertask.bean.LimsRunBoardHoleBean;
import com.sunwayworld.basemodule.business.ordertask.dao.LimsOrderTaskDao;
import com.sunwayworld.basemodule.business.ordertask.service.LimsOrderTaskService;
import com.sunwayworld.basemodule.business.ordertask.service.LimsRunBoardHoleService;
import com.sunwayworld.basemodule.business.ordertask.validators.LimsRunSubmitValidator;
import com.sunwayworld.basemodule.business.result.bean.LimsResultBean;
import com.sunwayworld.basemodule.business.result.bean.LimsRunBean;
import com.sunwayworld.basemodule.business.result.bean.LimsRunEquipBean;
import com.sunwayworld.basemodule.business.result.bean.LimsRunMaterialBean;
import com.sunwayworld.basemodule.business.result.outorder.bean.LimsRunOutsendBean;
import com.sunwayworld.basemodule.business.result.outorder.service.LimsRunOutsendService;
import com.sunwayworld.basemodule.business.result.service.LimsResultService;
import com.sunwayworld.basemodule.business.result.service.LimsRunEquipService;
import com.sunwayworld.basemodule.business.result.service.LimsRunMaterialService;
import com.sunwayworld.basemodule.business.result.service.LimsRunService;
import com.sunwayworld.basemodule.common.auditrecord.service.LimsAuditRecordService;
import com.sunwayworld.basemodule.coredata.test.bean.LimsTestBean;
import com.sunwayworld.basemodule.coredata.test.bean.LimsTestMethodBean;
import com.sunwayworld.basemodule.coredata.test.service.LimsTestMethodService;
import com.sunwayworld.basemodule.coredata.test.service.LimsTestService;
import com.sunwayworld.basemodule.samplemanage.sample.bean.LimsSampleBean;
import com.sunwayworld.basemodule.samplemanage.sample.bean.LimsSampleDerivativeBean;
import com.sunwayworld.basemodule.samplemanage.sample.service.LimsSampleDerivativeService;
import com.sunwayworld.basemodule.samplemanage.sample.service.LimsSampleService;
import com.sunwayworld.framework.at.annotation.AuditTrailEntry;
import com.sunwayworld.framework.at.annotation.AuditTrailType;
import com.sunwayworld.framework.context.ApplicationContextHelper;
import com.sunwayworld.framework.context.LocalContextHelper;
import com.sunwayworld.framework.context.concurrent.GikamConcurrentLocker;
import com.sunwayworld.framework.data.page.Page;
import com.sunwayworld.framework.data.page.Pagination;
import com.sunwayworld.framework.exception.InvalidDataException;
import com.sunwayworld.framework.i18n.I18nHelper;
import com.sunwayworld.framework.mybatis.mapper.MapperParameter;
import com.sunwayworld.framework.mybatis.mapper.MatchPattern;
import com.sunwayworld.framework.mybatis.mapper.SearchFilter;
import com.sunwayworld.framework.mybatis.page.PageRowBounds;
import com.sunwayworld.framework.restful.data.RestJsonWrapperBean;
import com.sunwayworld.framework.spring.annotation.GikamBean;
import com.sunwayworld.framework.support.PersistableHelper;
import com.sunwayworld.framework.utils.CollectionUtils;
import com.sunwayworld.framework.utils.NumberUtils;
import com.sunwayworld.framework.utils.ObjectUtils;
import com.sunwayworld.framework.utils.StringUtils;
import com.sunwayworld.framework.validator.data.annotation.ValidateDataWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Repository
@GikamBean
public class LimsOrderTaskServiceImpl implements LimsOrderTaskService {

    @Autowired
    private LimsOrderTaskDao limsOrderTaskDao;

    @Lazy
    @Autowired
    private LimsRunService runService;

    @Lazy
    @Autowired
    private LimsRunBoardHoleService runBoardHoleService;

    @Autowired
    @Lazy
    private LimsRunEquipService runEquipService;

    @Autowired
    @Lazy
    private LimsRunMaterialService runMaterialService;

    @Autowired
    @Lazy
    private LimsSampleService sampleService;

    @Autowired
    private LimsTestMethodService testMethodService;

    @Autowired
    private LimsSampleDerivativeService sampleDerivativeService;

    @Autowired
    @Lazy
    private LimsResultService resultService;

    @Lazy
    @Autowired
    private LimsAuditRecordService auditRecordService;

    @Lazy
    @Autowired
    private LimsTestService testService;

    @Autowired
    private LimsOrderTaskSupplementService orderTaskSupplementService;

    @Autowired
    @Lazy
    private LimsRunOutsendService limsRunOutsendService;

    @Autowired
    @Lazy
    private LimsSampleTypeService sampleTypeService;

    @Autowired
    @Lazy
    private LimsBatchSampleProductService limsBatchSampleProductService;

    @Override
    @SuppressWarnings("unchecked")
    public LimsOrderTaskDao getDao() {
        return limsOrderTaskDao;
    }

    @Override
    @Transactional
    @AuditTrailEntry(AuditTrailType.INSERT)
    public Long insert(RestJsonWrapperBean jsonWrapper) {
        LimsOrderTaskBean limsOrderTask = jsonWrapper.parseUnique(LimsOrderTaskBean.class);
        limsOrderTask.setId(ApplicationContextHelper.getNextIdentity());
        getDao().insert(limsOrderTask);
        return limsOrderTask.getId();
    }

    @Override
    public Page<LimsOrderTaskBean> selectTest(RestJsonWrapperBean wrapperBean) {
        MapperParameter parameter = wrapperBean.extractMapFilter();
        PageRowBounds pageRowBounds = wrapperBean.extractPageRowBounds();
        return this.selectPagination(() -> getDao().selectTest(parameter), pageRowBounds);
    }

    @Override
    @Transactional
    public void createRun(RestJsonWrapperBean wrapper) {
        LimsRunBean runBean = wrapper.parseUnique(LimsRunBean.class);
        if (ObjectUtils.isEmpty(runBean.getTestId())) return;
        LimsTestBean testBean = testService.selectById(NumberUtils.parseLong(runBean.getTestId()));
        runBean.setId(ApplicationContextHelper.getNextIdentity());
        runBean.setRunCode(ApplicationContextHelper.getNextSequence("T_LIMS_RUN"));
        runBean.setTestId(testBean.getId());
        runBean.setTestCode(testBean.getTestCode());
        runBean.setTestName(testBean.getTestName());
        List<Long> ids = null;
        int rowNum = 1;
        int colNum = 1;
        if ("96板孔".equals(runBean.getBoardSpec())) {
            ids = ApplicationContextHelper.getNextIdentityList(96);
            rowNum = 8;
            colNum = 12;
        } else if ("100板孔".equals(runBean.getBoardSpec())) {
            ids = ApplicationContextHelper.getNextIdentityList(100);
            rowNum = 10;
            colNum = 10;
        } else if ("384板孔".equals(runBean.getBoardSpec())) {
            ids = ApplicationContextHelper.getNextIdentityList(384);
            rowNum = 16;
            colNum = 24;
        } else {
            throw new InvalidDataException("板规格为空！");
        }
        List<LimsRunBoardHoleBean> insertRunBoardHoles = new ArrayList<>();
        for (int i = 0; i < rowNum; i++) {
            for (int j = 0; j < colNum; j++) {
                LimsRunBoardHoleBean runBoardHoleBean = new LimsRunBoardHoleBean();
                runBoardHoleBean.setId(ids.remove(0));
                runBoardHoleBean.setBoardId(runBean.getId());
                runBoardHoleBean.setColNum(colNum);
                runBoardHoleBean.setRowNum(rowNum);
                runBoardHoleBean.setY(i + 1);
                runBoardHoleBean.setX(j + 1);

                insertRunBoardHoles.add(runBoardHoleBean);
            }
        }

        LimsRunOutsendBean outsendBean = new LimsRunOutsendBean();
        outsendBean.setId(ApplicationContextHelper.getNextIdentity());
        outsendBean.setRunId(runBean.getId());
        limsRunOutsendService.getDao().insert(outsendBean);

        runBean.setOutSendId(outsendBean.getId());
        runService.getDao().insert(runBean);
        if (!insertRunBoardHoles.isEmpty()) {
            runBoardHoleService.getDao().fastInsert(insertRunBoardHoles);
        }
    }

    @Override
    public void addRunTasks(RestJsonWrapperBean wrapperBean) {
        List<LimsOrderTaskBean> parse = wrapperBean.parse(LimsOrderTaskBean.class);
        if (CollectionUtils.isEmpty(parse)) return;
        String runId = wrapperBean.getParamValue("runId");
        String runCode = wrapperBean.getParamValue("runCode");
        List<Long> parallelIds = parse.stream().map(LimsOrderTaskBean::getParallelId).collect(Collectors.toList());
        List<LimsOrderTaskBean> runTasks = selectListByFilter(SearchFilter.instance()
                .match("parallelId", parallelIds).filter(MatchPattern.OR));
        LimsRunBean runBean = runService.selectById(Long.parseLong(runId));
        runTasks.forEach(o -> {
            o.setRunId(Long.parseLong(runId));
            o.setRunCode(runCode);
            o.setAddInRun("1");
            o.setMethodCode(runBean.getMethodCode());
            o.setMethodDesc(runBean.getMethodDesc());
            o.setTesterId(runBean.getAnalystId());
            o.setTester(runBean.getAnalystName());
            o.setReviewer(runBean.getReviewer());
            o.setReviewerId(runBean.getReviewerId());
            o.setTestMethodId(runBean.getTestMethodId());
        });
        getDao().fastUpdate(runTasks, "runId", "runCode", "addInRun", "methodCode", "methodDesc", "testerId", "tester", "reviewer", "reviewerId", "testMethodId");
    }

    @Override
    @Transactional
    public void removeRunTasks(RestJsonWrapperBean wrapperBean) {
        List<LimsOrderTaskBean> parse = wrapperBean.parse(LimsOrderTaskBean.class);
        if (CollectionUtils.isEmpty(parse)) return;
        List<Long> parallelIds = parse.stream().map(LimsOrderTaskBean::getParallelId).collect(Collectors.toList());
        List<LimsOrderTaskBean> runTasks = selectListByFilter(SearchFilter.instance()
                .match("parallelId", parallelIds).filter(MatchPattern.OR));
        List<Long> holeIds = runTasks.stream().map(LimsOrderTaskBean::getBoardHoleId).filter(Objects::nonNull).collect(Collectors.toList());
        runTasks.forEach(o -> {
            o.setRunId(null);
            o.setRunCode(null);
            o.setBoardHoleId(null);
            o.setAddInRun("0");
            o.setMethodCode(null);
            o.setMethodDesc(null);
            o.setTesterId(null);
            o.setTester(null);
            o.setReviewer(null);
            o.setReviewerId(null);
            o.setTestMethodId(null);
        });
        getDao().fastUpdate(runTasks, "runId", "runCode", "addInRun", "boardHoleId", "methodCode", "methodDesc", "testerId", "tester", "reviewer", "reviewerId", "testMethodId");
        if (!CollectionUtils.isEmpty(holeIds)) {
            LimsRunBoardHoleBean runBoardHoleBean = new LimsRunBoardHoleBean();
            runBoardHoleBean.setOrderTaskId(null);
            runBoardHoleBean.setSampleFlag(null);
            runBoardHoleBean.setStockType("free");

            runBoardHoleService.getDao().updateByIds(runBoardHoleBean, holeIds, "orderTaskId", "sampleFlag", "stockType");
        }
    }

    @Override
    @Transactional
    public void deleteRun(RestJsonWrapperBean wrapperBean) {
        List<LimsRunBean> parse = wrapperBean.parse(LimsRunBean.class);
        if (CollectionUtils.isEmpty(parse)) return;
        List<Long> runIds = parse.stream().map(LimsRunBean::getId).collect(Collectors.toList());
        List<LimsOrderTaskBean> taskBeans = selectListByFilter(SearchFilter.instance()
                .match("runId", runIds).filter(MatchPattern.OR));
        taskBeans.forEach(o -> {
            o.setRunId(null);
            o.setRunCode(null);
            o.setBoardHoleId(null);
            o.setAddInRun("0");
            o.setMethodCode(null);
            o.setMethodDesc(null);
            o.setTesterId(null);
            o.setTester(null);
            o.setReviewer(null);
            o.setReviewerId(null);
            o.setTestMethodId(null);
        });
        List<LimsRunBoardHoleBean> holeBeans = runBoardHoleService.getDao().selectListByOneColumnValues(runIds, "boardId", Arrays.asList("id", "boardId"));
        if (!holeBeans.isEmpty()) {
            List<Long> holeIds = holeBeans.stream().map(LimsRunBoardHoleBean::getId).collect(Collectors.toList());
            runBoardHoleService.getDao().deleteByIdList(holeIds);
        }
        getDao().fastUpdate(taskBeans, "runId", "runCode", "addInRun", "boardHoleId", "methodCode", "methodDesc", "testerId", "tester", "reviewer", "reviewerId", "testMethodId");
        runService.getDao().deleteBy(parse);

        List<Long> delOutSendIds = parse.stream().map(LimsRunBean::getOutSendId).collect(Collectors.toList());
        limsRunOutsendService.getDao().deleteByIdList(delOutSendIds);
    }

    @Transactional
    @Override
    @ValidateDataWith(LimsRunSubmitValidator.class)
    public void batchSaveAssignment(RestJsonWrapperBean wrapperBean) {
        List<LimsRunBean> parse = wrapperBean.parse(LimsRunBean.class);
        String testerId = wrapperBean.getParamValue("testerId");
        String tester = wrapperBean.getParamValue("tester");
        String reviewer = wrapperBean.getParamValue("reviewer");
        String reviewerId = wrapperBean.getParamValue("reviewerId");
        Long testMethodId = Long.parseLong(wrapperBean.getParamValue("testMethodId"));
        String methodCode = wrapperBean.getParamValue("methodCode");
        String methodDesc = wrapperBean.getParamValue("methodDesc");
        String status = wrapperBean.getParamValue("status");
        if (CollectionUtils.isEmpty(parse)) return;
        parse.forEach(r -> {
            r.setMethodCode(methodCode);
            r.setMethodDesc(methodDesc);
            r.setAnalystId(testerId);
            r.setAnalystName(tester);
            r.setReviewer(reviewer);
            r.setReviewerId(reviewerId);
            r.setTestMethodId(testMethodId);
        });
        runService.getDao().fastUpdate(parse, "methodCode", "methodDesc", "analystId", "analystName", "reviewer", "reviewerId", "testMethodId");
        List<Long> runIds = parse.stream().map(LimsRunBean::getId).collect(Collectors.toList());
        List<LimsOrderTaskBean> taskBeans = selectListByFilter(SearchFilter.instance()
                .match("runId", runIds).filter(MatchPattern.OR));
        taskBeans.forEach(r -> {
            r.setMethodCode(methodCode);
            r.setMethodDesc(methodDesc);
            r.setTesterId(testerId);
            r.setTester(tester);
            r.setReviewer(reviewer);
            r.setReviewerId(reviewerId);
            r.setTestMethodId(testMethodId);
        });
        getDao().fastUpdate(taskBeans, "methodCode", "methodDesc", "testerId", "tester", "reviewer", "reviewerId", "testMethodId");

        if ("logged".equals(status)) {
            submit(parse);
        }
    }

    @Transactional
    @Override
    @ValidateDataWith(LimsRunSubmitValidator.class)
    public void submit(RestJsonWrapperBean wrapperBean) {
        List<LimsRunBean> parse = wrapperBean.parse(LimsRunBean.class);
        submit(parse);
    }

    private void submit(List<LimsRunBean> parse) {
        if (CollectionUtils.isEmpty(parse)) return;
        parse.forEach(r -> {
            GikamConcurrentLocker.block(r.getId().toString());
        });

        List<Long> ids = parse.stream().map(LimsRunBean::getId).collect(Collectors.toList());
        List<LimsRunBean> select = runService.selectListByIds(ids).stream().filter(r -> r.getStatus().contains("draft")).collect(Collectors.toList());
        if (select.isEmpty()) {
            return;
        }

        List<Long> runIds = select.stream().map(LimsRunBean::getId).collect(Collectors.toList());
        List<Long> testMethodIdList = select.stream().map(LimsRunBean::getTestMethodId).distinct().collect(Collectors.toList());
        List<LimsOrderTaskBean> taskBeans = selectListByFilter(SearchFilter.instance()
                .match("runId", runIds).filter(MatchPattern.OR));

        LocalDateTime now = LocalDateTime.now();
        select.forEach(r -> {
            r.setStatus("logged");
            r.setSubmitTime(now);
            // 获取当前批次下实验编号非空的数据T-板名称-孔编号
            Optional<LimsOrderTaskBean> orderTask = taskBeans.stream().filter(u->
                ObjectUtils.equals(u.getRunId(), r.getId()) && !StringUtils.isEmpty(u.getExt$Item("EXPNUMBER"))).findAny();
            if (orderTask.isPresent()) {
                LimsOrderTaskBean thisOrderTask = orderTask.get();
                if(thisOrderTask.getExt$Item("EXPNUMBER").contains("-")) {
                    List<String> expnumbers = Arrays.asList(thisOrderTask.getExt$Item("EXPNUMBER").split("-"));
                    if (expnumbers.size() > 1) {
                        // 至少有两段，直接取第二段
                        r.setBoardName(expnumbers.get(1));
                    }
                }
            }
        });
        runService.getDao().fastUpdate(select, "status", "submitTime", "boardName");

        /*//校验批次下是否有样本
        runBeans.stream().forEach(run->{
            List<LimsOrderTaskBean> tasks =taskBeans.stream().filter(task->run.getId().equals(task.getRunId())).collect(Collectors.toList());
            if(tasks.isEmpty()){
                throw new InvalidDataException(run.getRunCode()+I18nHelper.getMessage("RUN.SUBMIT.HINT"));//批次下没有样本，提交失败！
            }

        });*/
        taskBeans.forEach(o -> {
            LimsRunBean runBean = select.stream().filter(r -> r.getId().equals(o.getRunId())).findFirst().get();
            o.setMethodCode(runBean.getMethodCode());
            o.setMethodDesc(runBean.getMethodDesc());
            o.setTesterId(runBean.getAnalystId());
            o.setTester(runBean.getAnalystName());
            o.setReviewer(runBean.getReviewer());
            o.setReviewerId(runBean.getReviewerId());
            o.setTestMethodId(runBean.getTestMethodId());
            o.setStatus("logged");
        });
        getDao().fastUpdate(taskBeans, "methodCode", "methodDesc", "testerId", "tester", "reviewer", "reviewerId", "testMethodId", "status");

/*        List<LimsResultBean> resultList = taskBeans.stream().map(m -> {
            LimsResultBean resultBean = new LimsResultBean();
            resultBean.setOrderTaskId(m.getId());
            return resultBean;
        }).collect(Collectors.toList());
        resultService.getDao().deleteBy(resultList, "orderTaskId");
        resultService.copyOrderTaskInfoToResult(runBeans.get(0).getTestId(), testMethodIdList, taskBeans);

//        insertSampleDerivativeInfo(taskBeans);
        // 换成新的编码生成
        insertSampleDerivativeInfoNew(taskBeans);
        //根据实验批次生成设备信息
        insertEquipInfoByRunId(runBeans);
        //根据实验批次生成材料信息
        insertMaterialInfoByRunId(runBeans);*/

        // 从医学原型搬运
//        LoginUser loginPrincipal = LocalContextHelper.getLoginPrincipal();
//        ExecutorHelper.submit(() -> {
//            LocalContextHelper.setUserLogin(loginPrincipal);

        List<LimsResultBean> resultList = taskBeans.parallelStream().map(m -> {
            LimsResultBean resultBean = new LimsResultBean();
            resultBean.setOrderTaskId(m.getId());
            return resultBean;
        }).collect(Collectors.toList());
        resultService.getDao().deleteBy(resultList, "orderTaskId");
        resultService.copyOrderTaskInfoToResult(select.get(0).getTestId(), testMethodIdList, taskBeans);
        // 换成新的编码生成
        insertSampleDerivativeInfoNew(taskBeans);
        //根据实验批次生成设备信息
        insertEquipInfoByRunId(select);
        //根据实验批次生成材料信息
        insertMaterialInfoByRunId(select);
//        });

        //任务维度插入操作记录
        List<Long> taskIds = taskBeans.stream().map(LimsOrderTaskBean::getId).collect(Collectors.toList());
        auditRecordService.insertAuditRecords(taskIds, "T_LIMS_ORDER_TASK", I18nHelper.getMessage("LIMS.MODULE.MENUS.TREE.ORDERTASK"), I18nHelper.getMessage("GIKAM.MODAL.SUBMIT"), null);

        List<Long> sampleIds = taskBeans.stream().map(LimsOrderTaskBean::getSampleId).collect(Collectors.toList());
        auditRecordService.insertAuditRecords(sampleIds, "T_LIMS_SAMPLE", I18nHelper.getMessage("LIMS.MODULE.MENUS.TREE.ORDERTASK"), I18nHelper.getMessage("GIKAM.MODAL.SUBMIT"), null);

        // 触发公式 // 屏蔽掉，这里是重复触发公式了，之前测试加的
//        OrderTaskResultComputingEngine.getEngine(taskBeans.stream().map(LimsOrderTaskBean::getFolderId).distinct().collect(Collectors.toList())).compute();
//        ExecutorHelper.submit(() -> OrderTaskResultComputingEngine.getEngine(taskBeans.stream().map(LimsOrderTaskBean::getFolderId).distinct().collect(Collectors.toList())).compute());
    }

    @Override
    public void backScheduling(RestJsonWrapperBean wrapperBean) {
        List<LimsRunBean> runBeans = wrapperBean.parse(LimsRunBean.class);
        String reason = wrapperBean.getParamValue("reason");
        runBeans.forEach(r -> {
            r.setStatus("draft_reject");
            r.setRoomNo("");
            r.setTemperature("");
            r.setDampness("");
            r.setPressureFrom("");
            r.setPressureTo("");
            r.setRejectReason(reason);
        });
        runService.getDao().fastUpdate(runBeans, "status", "roomNo", "temperature"
                , "dampness", "pressureTo", "pressureFrom", "rejectReason");

        List<Long> runIds = runBeans.stream().map(LimsRunBean::getId).collect(Collectors.toList());
        List<LimsOrderTaskBean> taskBeans = selectListByFilter(SearchFilter.instance()
                .match("runId", runIds).filter(MatchPattern.OR));
        taskBeans.forEach(t -> t.setStatus("draft"));
        getDao().fastUpdate(taskBeans, "status");
        List<LimsResultBean> resultList = taskBeans.stream().map(m -> {
            LimsResultBean resultBean = new LimsResultBean();
            resultBean.setOrderTaskId(m.getId());
            return resultBean;
        }).collect(Collectors.toList());
        resultService.getDao().deleteBy(resultList, "orderTaskId");

        List<Long> taskIds = taskBeans.stream().map(LimsOrderTaskBean::getId).collect(Collectors.toList());
        List<LimsSampleDerivativeBean> sampleDerivativeBeans = sampleDerivativeService.selectListByFilter(SearchFilter.instance()
                .match("orderTaskId", taskIds).filter(MatchPattern.OR));
        if (!CollectionUtils.isEmpty(sampleDerivativeBeans)) {
            List<Long> sampleIds = sampleDerivativeBeans.stream().map(LimsSampleDerivativeBean::getDerivativeId).distinct().collect(Collectors.toList());
            sampleDerivativeService.getDao().deleteBy(sampleDerivativeBeans);
            sampleService.getDao().deleteByIdList(sampleIds);
        }

        List<LimsRunEquipBean> equipBeans = runBeans.stream().map(m -> {
            LimsRunEquipBean equipBean = new LimsRunEquipBean();
            equipBean.setRunId(m.getId());
            return equipBean;
        }).collect(Collectors.toList());
        runEquipService.getDao().deleteBy(equipBeans, "runId");

        List<LimsRunMaterialBean> materialBeans = runBeans.stream().map(m -> {
            LimsRunMaterialBean equipBean = new LimsRunMaterialBean();
            equipBean.setRunId(m.getId());
            return equipBean;
        }).collect(Collectors.toList());
        runMaterialService.getDao().deleteBy(materialBeans, "runId");

        //任务维度插入操作记录
        auditRecordService.insertAuditRecords(taskIds, "T_LIMS_ORDER_TASK", I18nHelper.getMessage("CORE.MENU.MENUNAME.NGS_TEST_AND_RESULT_ENTRY"), I18nHelper.getMessage("MODULE.BUSINESS.RESULT.BUTTON.RETURNBACK"), reason);

        List<Long> sampleIds = taskBeans.stream().map(LimsOrderTaskBean::getSampleId).collect(Collectors.toList());
        auditRecordService.insertAuditRecords(sampleIds, "T_LIMS_SAMPLE", I18nHelper.getMessage("CORE.MENU.MENUNAME.NGS_TEST_AND_RESULT_ENTRY"), I18nHelper.getMessage("MODULE.BUSINESS.RESULT.BUTTON.RETURNBACK"), reason);

    }

    private void insertEquipInfoByRunId(List<LimsRunBean> runBeanList) {
        List<Long> runIds = runBeanList.stream().map(LimsRunBean::getId).collect(Collectors.toList());
        if (!runIds.isEmpty()) {
            MapperParameter temp = new MapperParameter();
            temp.put("runId", StringUtils.join(runIds, ","));
            List<LimsRunEquipBean> runEquipBeans = runEquipService.selectEquipInfoByRunId(temp);
            if (!runEquipBeans.isEmpty()) {
                List<Long> equiptIds = ApplicationContextHelper.getNextIdentityList(runEquipBeans.size());
                int index = 0;
                for (LimsRunEquipBean RunEquipBean : runEquipBeans) {
                    RunEquipBean.setId(equiptIds.get(index));
                    index++;
                }
                runEquipService.getDao().fastInsert(runEquipBeans);
            }
        }
    }

    private void insertMaterialInfoByRunId(List<LimsRunBean> runBeanList) {
        List<Long> runIds = runBeanList.stream().map(LimsRunBean::getId).collect(Collectors.toList());
        if (!runIds.isEmpty()) {
            MapperParameter temp = new MapperParameter();
            temp.put("runId", StringUtils.join(runIds, ","));
            List<LimsRunMaterialBean> runMaterialBeans = runMaterialService.selectMaterialInfoByRunId(temp);
            if (!runMaterialBeans.isEmpty()) {
                List<Long> materialIds = ApplicationContextHelper.getNextIdentityList(runMaterialBeans.size());
                int index = 0;
                for (LimsRunMaterialBean runMaterialBean : runMaterialBeans) {
                    // 实际使用量默认为空
//                    runMaterialBean.setActualAmount(runMaterialBean.getRecommendedAmount());// 实际使用量默认和建议使用量一样
                    runMaterialBean.setId(materialIds.get(index));
                    index++;
                }
                runMaterialService.getDao().insert(runMaterialBeans);
            }
        }
    }

    public void insertSampleDerivativeInfoNew(List<LimsOrderTaskBean> orderTaskList) {
        if (orderTaskList.isEmpty()) {
            return;
        }
        List<Long> testMethodIdList = orderTaskList.stream().map(LimsOrderTaskBean::getTestMethodId).collect(Collectors.toList());

        MapperParameter temp = new MapperParameter();
        temp.setFilter(SearchFilter.instance().match("id", testMethodIdList).filter(MatchPattern.OR).match("DERIVATIVETYPE", "").filter(MatchPattern.DIFFER));
        List<LimsTestMethodBean> testMethodList = testMethodService.selectList(temp);
        if (testMethodList.isEmpty()) return;

        List<Long> sampleIdList = orderTaskList.stream().map(LimsOrderTaskBean::getSampleId).distinct().collect(Collectors.toList());
        List<LimsSampleBean> sampleBeans = sampleService.selectListByIds(sampleIdList);

        //检测任务map
        Map<Long, List<LimsOrderTaskBean>> orderTaskMaps = orderTaskList.stream().collect(Collectors.groupingBy(LimsOrderTaskBean::getTestMethodId));

        //获取样本类型LIST
        List<String> derivativeTypeList = testMethodList.stream()
                .map(LimsTestMethodBean::getDerivativeType)
                .filter(derivativeType -> !StringUtils.isEmpty(derivativeType))
                .distinct()
                .collect(Collectors.toList());
        temp.clear();
        //查询样本类型简码
        List<LimsSampleTypeBean> sampleTypeBeanList = sampleTypeService.selectListByFilter(SearchFilter.instance().match("sampleTypeCode", derivativeTypeList).filter(MatchPattern.OR));
        if (sampleTypeBeanList.isEmpty()) return;

        ArrayList<LimsSampleBean> insertSampleList = new ArrayList<>();
        ArrayList<LimsSampleDerivativeBean> insertSampleDerivativeList = new ArrayList<>();
        List<Long> parallelIdList = new ArrayList<>();
        parallelIdList.add(1L);

        List<String> oriNoList = orderTaskList.stream().map(t -> t.getExt$Item("oriNo")).distinct().collect(Collectors.toList());
        List<LimsSampleDerivativeBean> derivativeBeansAll = sampleDerivativeService.selectListByFilter(SearchFilter.instance()
                .match("sampleTypeCode", derivativeTypeList).filter(MatchPattern.OR)
                .match("oriNo", oriNoList).filter(MatchPattern.OR));

//        List<LimsSampleDerivativeBean> derivativeBeansAll = sampleDerivativeService.selectListByFilter(SearchFilter.instance().match("sampleTypeCode", derivativeTypeList).filter(MatchPattern.OR));

        for (LimsTestMethodBean testMethodBean : testMethodList) {
            List<LimsOrderTaskBean> orderTaskBeans = orderTaskMaps.get(testMethodBean.getId());
            if (CollectionUtils.isEmpty(orderTaskBeans)) {
                continue;
            }
            String startSampleCode;
            long i = 1L;
            for (LimsOrderTaskBean orderTaskBean : orderTaskBeans) {
                LimsSampleTypeBean sampleTypeBean = sampleTypeBeanList.stream().filter(s -> s.getSampleTypeCode().equals(testMethodBean.getDerivativeType())).findFirst().get();
                startSampleCode = orderTaskBean.getSampleCode();
                if (!insertSampleDerivativeList.isEmpty()) {
                    parallelIdList = insertSampleDerivativeList.stream().map(m -> NumberUtils.parseLong(m.getExt$Item("parallelId"))).distinct().collect(Collectors.toList());
                }

                String derivaSampleCode = null;
                if (parallelIdList.contains(orderTaskBean.getParallelId())) {
                    //TODO 并行id相同的task 即为混样后任务  生成衍生物时公用一个衍生物编号，共用一个样本的id
//                    derivaSampleCode = insertSampleDerivativeList.stream().filter(f -> orderTaskBean.getParallelId().equals(Long.parseLong(f.getExt$Item("parallelId")))).findFirst().get().getDerivativeNo();
                    insertSampleDerivativeList.stream().filter(f -> orderTaskBean.getParallelId().equals(Long.parseLong(f.getExt$Item("parallelId")))).findFirst().ifPresent(d -> {
                        //衍生物关系表
                        LimsSampleDerivativeBean sampleDerivativeBean = new LimsSampleDerivativeBean();
                        sampleDerivativeBean.setId(ApplicationContextHelper.getNextIdentity());
                        sampleDerivativeBean.setDerivativeId(d.getDerivativeId());
                        sampleDerivativeBean.setDerivativeNo(d.getDerivativeNo());
                        sampleDerivativeBean.setParentNo(orderTaskBean.getSampleCode());
                        sampleDerivativeBean.setParentId(orderTaskBean.getSampleId());
                        sampleDerivativeBean.setOrderTaskId(orderTaskBean.getId());
                        sampleDerivativeBean.setFolderId(orderTaskBean.getFolderId());
                        sampleDerivativeBean.setOrderId(orderTaskBean.getOrderId());
                        sampleDerivativeBean.setOriNo(d.getOriNo());

                        sampleDerivativeBean.setExt$Item("parallelId", orderTaskBean.getParallelId().toString());

                        //衍生物表
                        insertSampleDerivativeList.add(sampleDerivativeBean);
                    });
                } else {
                    //衍生物首字母同父样本  包含混样样本M、质控样本N,P等
                    String firstCode = startSampleCode.substring(0, 1);

                    String[] parts = startSampleCode.split("-");
                    String sampleCodeFront = "";

                    String qcsampleflg = orderTaskBean.getExt$Item("qcsampleflg");
                    if (StringUtils.isBlank(qcsampleflg) || !"1".equals(qcsampleflg)) {
                        if (parts.length > 1) {
                            List<Character> numbers = Arrays.asList('0', '1', '2', '3', '4', '5', '6', '7', '8', '9');
                            AtomicInteger index_1 = new AtomicInteger(3);
                            for (int j = 0; j < startSampleCode.length(); j++) {
                                char c = startSampleCode.charAt(j);
                                if (numbers.stream().anyMatch(n -> n.equals(c))) {
                                    index_1.getAndSet(j);
                                    break;
                                }
                            }
                            sampleCodeFront = String.format("%s%s%s", firstCode, sampleTypeBean.getBriefCode(), parts[0].substring(index_1.get()));
                        } else {
                            sampleCodeFront = String.format("%s%s%s", firstCode, sampleTypeBean.getBriefCode(), parts[0].substring(1));
                        }
                    } else {
                        String qcBriefCode = parts[0].substring(0, 1);
                        if (parts.length > 1) {
                            List<Character> numbers = Arrays.asList('0', '1', '2', '3', '4', '5', '6', '7', '8', '9');
                            AtomicInteger index_1 = new AtomicInteger(3);
                            for (int j = 0; j < startSampleCode.length(); j++) {
                                char c = startSampleCode.charAt(j);
                                if (numbers.stream().anyMatch(n -> n.equals(c))) {
                                    index_1.getAndSet(j);
                                    break;
                                }
                            }
                            sampleCodeFront = String.format("%s%s%s", qcBriefCode, sampleTypeBean.getBriefCode(), parts[0].substring(index_1.get()));
                        } else {
                            sampleCodeFront = String.format("%s%s%s", qcBriefCode, sampleTypeBean.getBriefCode(), parts[0].substring(1));
                        }
                    }

                    String finalSampleCodeFront = sampleCodeFront;
                    List<LimsSampleDerivativeBean> derivativeBeans = derivativeBeansAll.stream().filter(d -> !StringUtils.isBlank(d.getDerivativeNo()) && d.getDerivativeNo().contains(finalSampleCodeFront)).collect(Collectors.toList());
                    if (derivativeBeans.isEmpty()) {
                        derivaSampleCode = sampleCodeFront + "-1";
                        int max = 1;
                        boolean flag = true;
                        while (flag) {
                            boolean find = false;
                            for (LimsSampleBean s : insertSampleList) {
                                if (s.getSampleCode().equals(derivaSampleCode)) {
                                    max++;
                                    derivaSampleCode = sampleCodeFront + "-" + max;
                                    find = true;
                                    break;
                                }
                            }
                            if (!find) {
                                flag = false;
                            }
                        }
                    } else {
                        int max = 1;
                        for (LimsSampleDerivativeBean d : derivativeBeans) {
                            String derivativeNo = d.getDerivativeNo();
                            String[] parts_2 = derivativeNo.split("-");
                            if (parts_2.length > 1 && Integer.parseInt(parts_2[1]) > max) {
                                max = Integer.parseInt(parts_2[1]);
                            }
                        }
                        max++;
                        derivaSampleCode = sampleCodeFront + "-" + max;
                        boolean flag = true;
                        while (flag) {
                            boolean find = false;
                            for (LimsSampleBean s : insertSampleList) {
                                if (s.getSampleCode().equals(derivaSampleCode)) {
                                    max++;
                                    derivaSampleCode = sampleCodeFront + "-" + max;
                                    find = true;
                                    break;
                                }
                            }
                            if (!find) {
                                flag = false;
                            }
                        }
                    }
                    LimsSampleBean sampleBean = sampleBeans.stream().filter(s -> s.getId().equals(orderTaskBean.getSampleId())).findFirst().get();
                    //插入衍生物信息到样本表
                    LimsSampleBean derivative = new LimsSampleBean();
                    derivative.setId(ApplicationContextHelper.getNextIdentity());
                    derivative.setSampleCode(derivaSampleCode);
                    derivative.setInHandle("3");
//                    derivative.setHandleType("wait");
                    derivative.setStatus("inExperiment");
                    derivative.setParentNo(orderTaskBean.getSampleCode());
                    //样本类型
                    derivative.setSampleType(testMethodBean.getDerivativeTypeName());
                    derivative.setSampleTypeCode(testMethodBean.getDerivativeType());
                    derivative.setOriginalFlg("0");
                    derivative.setUseFlg("1");
                    derivative.setOriNo(sampleBean.getOriNo());
                    // 继承父样本的分院样本编号，实验样本编号
                    derivative.setHissampleCode(orderTaskBean.getExt$Item("HISSAMPLECODE"));
                    derivative.setExpNumber(orderTaskBean.getExt$Item("EXPNUMBER"));
                    derivative.setCreatedById(LocalContextHelper.getLoginUserId());
                    derivative.setCreatedByName(LocalContextHelper.getLoginUserName());
                    derivative.setCreatedByOrgId(LocalContextHelper.getLoginOrgId());
                    derivative.setCreatedByOrgName(LocalContextHelper.getLoginOrgName());
                    derivative.setCreatedTime(LocalDateTime.now());

                    //衍生物关系表
                    LimsSampleDerivativeBean sampleDerivativeBean = new LimsSampleDerivativeBean();
                    sampleDerivativeBean.setId(ApplicationContextHelper.getNextIdentity());
                    sampleDerivativeBean.setDerivativeId(derivative.getId());
                    sampleDerivativeBean.setDerivativeNo(derivative.getSampleCode());
                    sampleDerivativeBean.setParentNo(orderTaskBean.getSampleCode());
                    sampleDerivativeBean.setParentId(orderTaskBean.getSampleId());
                    sampleDerivativeBean.setOrderTaskId(orderTaskBean.getId());
                    sampleDerivativeBean.setFolderId(orderTaskBean.getFolderId());
                    sampleDerivativeBean.setOrderId(orderTaskBean.getOrderId());
                    sampleDerivativeBean.setOriNo(sampleBean.getOriNo());

                    sampleDerivativeBean.setExt$Item("parallelId", orderTaskBean.getParallelId().toString());

                    //样本表
                    insertSampleList.add(derivative);
                    //衍生物表
                    insertSampleDerivativeList.add(sampleDerivativeBean);
                }
            }
        }
        //插入表
        if (!CollectionUtils.isEmpty(insertSampleList) && !CollectionUtils.isEmpty(insertSampleDerivativeList)) {
            sampleService.getDao().fastInsert(insertSampleList);
            sampleDerivativeService.getDao().fastInsert(insertSampleDerivativeList);
/*            ExecutorHelper.submitAfterCommitTransaction(() -> {
                sampleService.getDao().fastInsert(insertSampleList);
                sampleDerivativeService.getDao().fastInsert(insertSampleDerivativeList);
            });*/
        }
    }

    private void insertSampleDerivativeInfo(List<LimsOrderTaskBean> orderTaskList) {
        List<Long> testMethodIdList = orderTaskList.stream().map(LimsOrderTaskBean::getTestMethodId).collect(Collectors.toList());

        MapperParameter temp = new MapperParameter();
        temp.setFilter(SearchFilter.instance().match("id", testMethodIdList).filter(MatchPattern.OR).match("DERIVATIVETYPE", "").filter(MatchPattern.DIFFER));
        List<LimsTestMethodBean> testMethodList = testMethodService.selectList(temp);
        if (testMethodList.isEmpty()) return;

        List<Long> sampleIdList = orderTaskList.stream().map(LimsOrderTaskBean::getSampleId).distinct().collect(Collectors.toList());
        List<LimsSampleBean> sampleBeans = sampleService.selectListByIds(sampleIdList);

        ArrayList<LimsSampleBean> insertSampleList = new ArrayList<>();
        ArrayList<LimsSampleDerivativeBean> insertSampleDerivativeList = new ArrayList<>();
        for (LimsOrderTaskBean orderTaskBean : orderTaskList) {
            Optional<LimsTestMethodBean> any = testMethodList.stream().filter(t -> t.getId().equals(orderTaskBean.getTestMethodId())).findAny();
            if (!any.isPresent()) continue;
            LimsTestMethodBean testMethodBean = any.get();
            LimsSampleBean sampleBean = sampleBeans.stream().filter(s -> s.getId().equals(orderTaskBean.getSampleId())).findFirst().get();
            //插入衍生物信息到样本表
            LimsSampleBean derivative = new LimsSampleBean();
            derivative.setId(ApplicationContextHelper.getNextIdentity());
            derivative.setSampleCode(ApplicationContextHelper.getNextSequence("T_LIMS_SAMPLE_DERIVATIVE", "SD"));
            derivative.setStatus("inExperiment");
            derivative.setInHandle("3");
            derivative.setHandleType("wait");
            derivative.setParentNo(orderTaskBean.getSampleCode());
            //样本类型
            derivative.setSampleType(testMethodBean.getDerivativeTypeName());
            derivative.setSampleTypeCode(testMethodBean.getDerivativeType());
            derivative.setOriginalFlg("0");
            derivative.setUseFlg("1");
            derivative.setOriNo(sampleBean.getOriNo());
            // 继承父样本的分院样本编号，实验样本编号
            derivative.setHissampleCode(orderTaskBean.getExt$Item("HISSAMPLECODE"));
            derivative.setExpNumber(orderTaskBean.getExt$Item("EXPNUMBER"));
            //衍生物关系表
            LimsSampleDerivativeBean sampleDerivativeBean = new LimsSampleDerivativeBean();
            sampleDerivativeBean.setId(ApplicationContextHelper.getNextIdentity());
            sampleDerivativeBean.setDerivativeId(derivative.getId());
            sampleDerivativeBean.setDerivativeNo(derivative.getSampleCode());
            sampleDerivativeBean.setParentNo(orderTaskBean.getSampleCode());
            sampleDerivativeBean.setParentId(orderTaskBean.getSampleId());
            sampleDerivativeBean.setOrderTaskId(orderTaskBean.getId());
            sampleDerivativeBean.setFolderId(orderTaskBean.getFolderId());
            sampleDerivativeBean.setOrderId(orderTaskBean.getOrderId());
            sampleDerivativeBean.setOriNo(sampleBean.getOriNo());

            //样本表
            insertSampleList.add(derivative);
            //衍生物表
            insertSampleDerivativeList.add(sampleDerivativeBean);
        }
        //插入表
        if (!CollectionUtils.isEmpty(insertSampleList) && !CollectionUtils.isEmpty(insertSampleDerivativeList)) {
            sampleService.getDao().insert(insertSampleList);
            sampleDerivativeService.getDao().insert(insertSampleDerivativeList);
        }
    }

    @Override
    public Page<LimsOrderTaskBean> selectOrderTaskWithResult(RestJsonWrapperBean wrapperBean) {
        MapperParameter parameter = wrapperBean.extractMapFilter();
        PageRowBounds rowBounds = wrapperBean.extractPageRowBounds();
        Page<LimsOrderTaskBean> page = this.selectPagination(parameter, rowBounds);
        if (page.getRows().isEmpty()) {
            return page;
        }
        List<LimsOrderTaskBean> itemList = page.getRows();
        // 获取任务单的分析项列表：
        if (!itemList.isEmpty()) {
            List<LimsResultBean> resultBeanList = resultService
                    .selectListByFilter(SearchFilter.instance().match("orderTaskId", itemList.stream().map(LimsOrderTaskBean::getId).collect(Collectors.toList())).filter(MatchPattern.OR));
            itemList.forEach(orderTaskBean -> {
                List<LimsResultBean> resultList = resultBeanList.stream().filter(resultBean -> resultBean.getOrderTaskId().equals(orderTaskBean.getId())).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(resultList)) {
                    Map<String, String> analyteInfo = new HashMap<>();
                    resultList.forEach(resultBean -> {
                        String analyteId = ObjectUtils.toString(resultBean.getAnalyteId());
                        orderTaskBean.setExt$Item(analyteId, resultBean.getFinalResult());
                        analyteInfo.put(analyteId, resultBean.getExt$Item("color"));
                        if ("F".equalsIgnoreCase(resultBean.getAnalType())) {
                            // 如果结果类型为富文本，则在界面仅显示：详情，用作富文本外链点击
                            if (StringUtils.isEmpty(resultBean.getFinalResult())) {
                                orderTaskBean.setExt$Item(analyteId, "编辑");
//                                analyteInfo.put(analyteId, "#FF4500");
                            } else {
                                orderTaskBean.setExt$Item(analyteId, "详情");
                            }
                        }
                    });
                    orderTaskBean.setExt$Item("resultInfo", JSONObject.toJSONString(analyteInfo, SerializerFeature.WriteMapNullValue));
                }
            });
        }
        return new Pagination<>(page, itemList);
    }

    @Override
    public Page<LimsOrderTaskBean> selectOrderTaskWithOriginalResult(RestJsonWrapperBean wrapperBean) {
        MapperParameter parameter = wrapperBean.extractMapFilter();
        PageRowBounds rowBounds = wrapperBean.extractPageRowBounds();
        Page<LimsOrderTaskBean> page = this.selectPagination(parameter, rowBounds);
        if (page.getRows().isEmpty()) {
            return page;
        }
        List<LimsOrderTaskBean> itemList = page.getRows();
        // 获取任务单的分析项列表：
        if (!itemList.isEmpty()) {
            List<LimsResultBean> resultBeanList = resultService
                    .selectListByFilter(SearchFilter.instance().match("orderTaskId", itemList.stream().map(LimsOrderTaskBean::getId).collect(Collectors.toList())).filter(MatchPattern.OR));
            itemList.forEach(orderTaskBean -> {
                List<LimsResultBean> resultList = resultBeanList.stream().filter(resultBean -> resultBean.getOrderTaskId().equals(orderTaskBean.getId())).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(resultList)) {
                    Map<String, String> analyteInfo = new HashMap<>();
                    resultList.forEach(resultBean -> {
                        String analyteId = ObjectUtils.toString(resultBean.getAnalyteId());
                        orderTaskBean.setExt$Item(analyteId, resultBean.getOriginalResult());
                        analyteInfo.put(analyteId, resultBean.getExt$Item("color"));
                        if ("F".equalsIgnoreCase(resultBean.getAnalType())) {
                            // 如果结果类型为富文本，则在界面仅显示：详情，用作富文本外链点击
                            if (StringUtils.isEmpty(resultBean.getFinalResult())) {
                                orderTaskBean.setExt$Item(analyteId, "编辑");
//                                analyteInfo.put(analyteId, "#FF4500");
                            } else {
                                orderTaskBean.setExt$Item(analyteId, "详情");
                            }
                        }
                    });
                    orderTaskBean.setExt$Item("resultInfo", JSONObject.toJSONString(analyteInfo, SerializerFeature.WriteMapNullValue));
                }
            });
        }
        return new Pagination<>(page, itemList);
    }

    @Override
    public List<LimsOrderTaskBean> selectTestSelections(RestJsonWrapperBean wrapperBean, String status) {
        MapperParameter parameter = wrapperBean.extractMapFilter();
        parameter.put("status", status);
        parameter.put("userId", LocalContextHelper.getLoginUserId());
        return this.getDao().selectTest(parameter).stream().map(m -> PersistableHelper.mapToPersistable(m, LimsOrderTaskBean.class)).collect(Collectors.toList());
    }

    @Override
    public List<LimsOrderTaskBean> testSelectableList(RestJsonWrapperBean wrapper) {
        List<Map<String, Object>> mapList = getDao().testSelectableList(wrapper.extractMapFilter());
        if (mapList.isEmpty()) return CollectionUtils.emptyList();
        return mapList.stream().map(m -> PersistableHelper.mapToPersistable(m, LimsOrderTaskBean.class)).collect(Collectors.toList());
    }

    @Override
    public Page<LimsOrderTaskBean> selectOrderTaskWithSupplement(RestJsonWrapperBean wrapper) {
        MapperParameter parameter = wrapper.extractMapFilter();
        PageRowBounds rowBounds = wrapper.extractPageRowBounds();
        Page<LimsOrderTaskBean> page = this.selectPagination(() -> getDao().selectByCondition(parameter), rowBounds);
        if (page.getRows().isEmpty()) {
            return page;
        }
        List<LimsOrderTaskBean> itemList = page.getRows();
        // 获取工序补充信息
        if (!itemList.isEmpty()) {
            List<LimsOrderTaskSupplementBean> orderTaskSupplementBeanList = orderTaskSupplementService.selectListByFilter(SearchFilter.instance()
                    .match("orderTaskId", itemList.stream().map(LimsOrderTaskBean::getId).collect(Collectors.toList())).filter(MatchPattern.OR));
            itemList.forEach(orderTask -> {
                List<LimsOrderTaskSupplementBean> orderTaskSupplementList = orderTaskSupplementBeanList.stream().filter(e -> e.getOrderTaskId().equals(orderTask.getId())).collect(Collectors.toList());
                if (!orderTaskSupplementList.isEmpty()) {
                    Map<String, String> fieldInfo = new HashMap<>();
                    orderTaskSupplementList.forEach(supplement -> {
                        orderTask.setExt$Item(supplement.getFieldName(), supplement.getFieldValue());
                        fieldInfo.put(supplement.getFieldName(), supplement.getFieldValue());
                    });
                    orderTask.setExt$Item("supplementinfo", JSONObject.toJSONString(fieldInfo, SerializerFeature.WriteMapNullValue));
                }
            });
        }
        return new Pagination<>(page, itemList);
    }

    @Override
    public List<LimsOrderTaskBean> selectPreFolderByOrderTask(MapperParameter parameter) {
        List<Map<String, Object>> maps = getDao().selectPreFolderByOrderTask(parameter);
        return maps.isEmpty() ? Collections.emptyList() :
                maps.stream().map(e -> PersistableHelper.mapToPersistable(e, LimsOrderTaskBean.class)).collect(Collectors.toList());
    }

    @Override
    public List<LimsOrderTaskBean> selectDerivativeTask(MapperParameter parameter) {
        List<Map<String, Object>> maps = getDao().selectDerivativeTask(parameter);
        return maps.isEmpty() ? Collections.emptyList() :
                maps.stream().map(e -> PersistableHelper.mapToPersistable(e, LimsOrderTaskBean.class)).collect(Collectors.toList());
    }

    @Override
    @Transactional
    public void createRunWithTest(RestJsonWrapperBean wrapperBean) {
        List<LimsRunBean> runBeans = wrapperBean.parse(LimsRunBean.class, 0);
        if (runBeans.isEmpty() || runBeans.get(0).getTestId() == null) {
            return;
        }
        LimsRunBean runBean = runBeans.get(0);
        if (ObjectUtils.isEmpty(runBean.getTestId())) return;
        LimsTestBean testBean = testService.selectById(NumberUtils.parseLong(runBean.getTestId()));
        runBean.setId(ApplicationContextHelper.getNextIdentity());
        runBean.setRunCode(ApplicationContextHelper.getNextSequence("T_LIMS_RUN"));
        runBean.setTestId(testBean.getId());
        runBean.setTestCode(testBean.getTestCode());
        runBean.setTestName(testBean.getTestName());

        // 通过添加批次添加的，布板默认为0
        runBean.setHasBoardFlag("0");

        if (!StringUtils.isBlank(runBean.getBoardSpec())) {
            runBean.setHasBoardFlag("1");

            List<Long> ids = null;
            int rowNum = 1;
            int colNum = 1;
            if ("96板孔".equals(runBean.getBoardSpec())) {
                ids = ApplicationContextHelper.getNextIdentityList(96);
                rowNum = 8;
                colNum = 12;
            } else if ("100板孔".equals(runBean.getBoardSpec())) {
                ids = ApplicationContextHelper.getNextIdentityList(100);
                rowNum = 10;
                colNum = 10;
            } else if ("384板孔".equals(runBean.getBoardSpec())) {
                ids = ApplicationContextHelper.getNextIdentityList(384);
                rowNum = 16;
                colNum = 24;
            } else {
                throw new InvalidDataException("板规格为空！");
            }
            List<LimsRunBoardHoleBean> insertRunBoardHoles = new ArrayList<>();
            for (int i = 0; i < rowNum; i++) {
                for (int j = 0; j < colNum; j++) {
                    LimsRunBoardHoleBean runBoardHoleBean = new LimsRunBoardHoleBean();
                    runBoardHoleBean.setId(ids.remove(0));
                    runBoardHoleBean.setBoardId(runBean.getId());
                    runBoardHoleBean.setColNum(colNum);
                    runBoardHoleBean.setRowNum(rowNum);
                    runBoardHoleBean.setY(i + 1);
                    runBoardHoleBean.setX(j + 1);

                    insertRunBoardHoles.add(runBoardHoleBean);
                }
            }
            if (!insertRunBoardHoles.isEmpty()) {
                runBoardHoleService.getDao().fastInsert(insertRunBoardHoles);
            }
        }

        LimsRunOutsendBean outsendBean = new LimsRunOutsendBean();
        outsendBean.setId(ApplicationContextHelper.getNextIdentity());
        outsendBean.setRunId(runBean.getId());
        limsRunOutsendService.getDao().insert(outsendBean);

        runBean.setOutSendId(outsendBean.getId());
        runService.getDao().insert(runBean);

        if (wrapperBean.getBodyList().size() > 1) {
            // 如果有挑选工序任务的话就加到这个批次上
            List<LimsOrderTaskBean> parse = wrapperBean.parse(LimsOrderTaskBean.class, 1);
            if (CollectionUtils.isEmpty(parse)) return;
            Long runId = runBean.getId();
            String runCode = runBean.getRunCode();
            List<Long> parallelIds = parse.stream().map(LimsOrderTaskBean::getParallelId).collect(Collectors.toList());
            List<LimsOrderTaskBean> runTasks = selectListByFilter(SearchFilter.instance()
                    .match("parallelId", parallelIds).filter(MatchPattern.OR));
            LimsOrderTaskBean update = new LimsOrderTaskBean();
            update.setRunId(runId);
            update.setRunCode(runCode);
            update.setAddInRun("1");
            List<Long> updateTaskIds = runTasks.stream().map(LimsOrderTaskBean::getId).collect(Collectors.toList());
            getDao().updateByIds(update, updateTaskIds, "runId", "runCode", "addInRun");
        }
    }

    @Override
    public List<LimsOrderTaskBean> selectAbnormalTestSelections() {
        MapperParameter parameter = new MapperParameter();
        parameter.put("status", "abnormal");
        parameter.put("abnormalHandlePersonId", LocalContextHelper.getLoginUserId());
        return this.getDao().selectTest(parameter).stream().map(m -> PersistableHelper.mapToPersistable(m, LimsOrderTaskBean.class)).collect(Collectors.toList());
    }

    @Transactional
    @Override
    public void abnormal(RestJsonWrapperBean wrapperBean) {
        List<LimsOrderTaskBean> parse = wrapperBean.parse(LimsOrderTaskBean.class);
        if (CollectionUtils.isEmpty(parse)) return;
        String reason = wrapperBean.getParamValue("reason");
        List<Long> parallelIds = parse.stream().map(LimsOrderTaskBean::getParallelId).collect(Collectors.toList());
        List<LimsOrderTaskBean> stopTaskList = this.selectListByFilter(SearchFilter.instance()
                .match("parallelId", parallelIds).filter(MatchPattern.OR));

        List<Long> folderIdList = stopTaskList.stream().map(LimsOrderTaskBean::getFolderId).distinct().collect(Collectors.toList());
        List<Long> sampleIds = stopTaskList.stream().map(LimsOrderTaskBean::getSampleId).distinct().collect(Collectors.toList());

        runService.abnormalStop(stopTaskList, reason);

        //任务维度插入操作记录
        List<Long> taskIds = stopTaskList.stream().map(LimsOrderTaskBean::getId).collect(Collectors.toList());
        auditRecordService.insertAuditRecords(taskIds, "T_LIMS_ORDER_TASK", I18nHelper.getMessage("LIMS.MODULE.MENUS.TREE.ORDERTASK"), I18nHelper.getMessage("终止实验"), reason);
        auditRecordService.insertAuditRecords(sampleIds, "T_LIMS_SAMPLE", I18nHelper.getMessage("LIMS.MODULE.MENUS.TREE.ORDERTASK"), I18nHelper.getMessage("终止实验"), reason);

//        limsBatchSampleProductService.setBatchProductStatus(folderIdList);
        limsBatchSampleProductService.setBatchProductWithStatus(folderIdList, "expStop");
    }
}
